package pl.put.augrelshooter.logic.detection;

import java.util.Iterator;
import java.util.List;

import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

import pl.put.augrelshooter.logic.detection.opencv.ColorBlobDetector;
import pl.put.augrelshooter.logic.detection.opencv.DetectedObject;
import pl.put.augrelshooter.logic.game.badges.Badge;
import android.graphics.Bitmap;

public class ObjectsDetector {
	private ColorBlobDetector blobDetector;
	private List<DetectedObject> detected;

	public ObjectsDetector() {
		blobDetector = new ColorBlobDetector();
	}

	public void detectOnScene(Mat img, Badge badge) {

		detected = detectColor(img, badge.getBadgeOuterColor().getColor(), badge.getBadgeOuterColor().getRadius());
		List<DetectedObject> detectedInner = detectColor(img, badge.getBadgeInnerColor().getColor(), badge.getBadgeInnerColor().getRadius());

		Iterator<DetectedObject> detectedIterator = detected.iterator();

		while (detectedIterator.hasNext()) {
			DetectedObject outer = detectedIterator.next();

			boolean hasSomeInner = false;

			for (DetectedObject inner : detectedInner) {
				if (containsLeftSide(outer, inner) && containsRightSide(outer, inner) && containsTop(outer, inner) && containsBottom(outer, inner)) {
					hasSomeInner = true;
					break;
				}
			}

			if (!hasSomeInner) {
				detectedIterator.remove();
			}
		}
	}

	public List<DetectedObject> getDetectedObjects() {
		return detected;
	}

	public Mat getMatFromBitmap(Bitmap bitmap) {
		Mat img = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC1);

		Utils.bitmapToMat(bitmap, img);

		int originalWidth = img.width();
		int originalHeight = img.height();
		Imgproc.resize(img, img, new Size(originalWidth * 0.8, originalHeight * 0.8));
		Imgproc.resize(img, img, new Size(originalWidth, originalHeight));

		return img;
	}

	private boolean containsBottom(DetectedObject outer, DetectedObject inner) {
		return inner.getCenter().y + inner.getSize() < outer.getCenter().y + outer.getSize();
	}

	private boolean containsTop(DetectedObject outer, DetectedObject inner) {
		return inner.getCenter().y - inner.getSize() > outer.getCenter().y - outer.getSize();
	}

	private boolean containsRightSide(DetectedObject outer, DetectedObject inner) {
		return inner.getCenter().x + inner.getSize() < outer.getCenter().x + outer.getSize();
	}

	private boolean containsLeftSide(DetectedObject outer, DetectedObject inner) {
		return inner.getCenter().x - inner.getSize() > outer.getCenter().x - outer.getSize();
	}

	private List<DetectedObject> detectColor(Mat img, Scalar color, Scalar colorRadius) {
		blobDetector.setColorRadius(colorRadius);
		blobDetector.setHsvColor(color);
		
		blobDetector.process(img);

		List<DetectedObject> detected = blobDetector.getDetectedObjects();
		return detected;
	}
	
	public ColorBlobDetector getBlobDetector() {
		return blobDetector;
	}
}
